package preprocess;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.w3c.dom.*;
import java.io.*;
import java.util.*;
public class One_Instance_Filter {
	public static void main(String args[]){
		String xml = "pubmed_result.xml"; // modify the path....
		One_Instance_Filter oif = new One_Instance_Filter();
		oif.XMLParser(xml);
	}
	public List <ArticleUnit> XMLParser(String xml_file){
	    List <ArticleUnit> ArticleUnits = new ArrayList<ArticleUnit>();
		Document dom;
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try{
        	DocumentBuilder db = dbf.newDocumentBuilder();
        	dom = db.parse(xml_file);
           NodeList Articles = dom.getElementsByTagName("PubmedArticle");   
           for(int i=0; i<Articles.getLength(); i++){ // deal with each article
        	   String pmid = null, title = null, abstract_info = null, journal_title = null;
        	   List<Name> author_names = new ArrayList<Name>();
        	   List<String> Mesh = new ArrayList<String>();
        	   List<String>Major_Mesh = new ArrayList<String>();
        	  NodeList Medline_citation = Articles.item(i).getChildNodes().item(1).getChildNodes(); // corresponding to MedlineCitation tag.
        	  for(int j=0; j<Medline_citation.getLength(); j++){
        		  if(Medline_citation.item(j).getNodeName().equals("PMID")){
        			  pmid = Medline_citation.item(j).getTextContent();
        		  }
        		  if(Medline_citation.item(j).getNodeName().equals("Article")){ // containing journal, title, abstract and author name
        			  NodeList article = Medline_citation.item(j).getChildNodes();
        			  for(int k=0; k<article.getLength(); k++){
        				  if(article.item(k).getNodeName().equals("Journal")){ // get journal
        					  NodeList journal_info = article.item(k).getChildNodes();
        					  for(int s=0; s<journal_info.getLength(); s++){
        						  if(journal_info.item(s).getNodeName().equals("Title"))
        							  journal_title = journal_info.item(s).getTextContent();
        					  }
        				  }
        				  if(article.item(k).getNodeName().equals("ArticleTitle")){
        					  title = article.item(k).getTextContent();
        				  }
        				  if(article.item(k).getNodeName().equals("Abstract")){
        					  abstract_info = article.item(k).getTextContent();
        				  }
        				  if(article.item(k).getNodeName().equals("AuthorList")){
        					  NodeList authors = article.item(k).getChildNodes();
        					  for(int s=0; s<authors.getLength(); s++){
        						  if(authors.item(s).getNodeName().equals("Author"))
        							  author_names.add(GetNameInfo(authors.item(s)));
        					  }
        				  }
        			  }
        		  }
        		  if(Medline_citation.item(j).getNodeName().equals("MeshHeadingList")){
        			  NodeList Meshheadings = Medline_citation.item(j).getChildNodes();
        			  for(int k=0; k<Meshheadings.getLength(); k++){
        				  if(Meshheadings.item(k).getNodeName().equals("MeshHeading"))
        					  AddMeshInfo(Meshheadings.item(k),Mesh,Major_Mesh);
        			  }
        		  }
        	  }
        	 if(pmid != null && title != null && abstract_info != null){
        		 // check whether there is only one instance of cold.
        		String localtext = IsOneInstance(pmid, title,abstract_info);
        		 if(localtext != null){
        			// System.out.println(localtext);
        			 ArticleUnit article_unit = new ArticleUnit();
        			 article_unit.setAbstract_info(abstract_info);
        			 article_unit.setTitle(title);
        			 article_unit.setPmid(pmid);
        			 article_unit.setJournal(journal_title);
        			 article_unit.setAuthor_names(author_names);
        			 article_unit.setMajorMesh(Major_Mesh);
        			 article_unit.setMesh(Mesh);
        			 article_unit.setCold_Sentence();
        			 article_unit.setBigram_profile(localtext);
        			 ArticleUnits.add(article_unit);
        		 }
        	 }
           }
         
        }catch (ParserConfigurationException pce) {
            System.out.println(pce.getMessage());
        } catch (SAXException se) {
            System.out.println(se.getMessage());
        } catch (IOException ioe) {
            System.err.println(ioe.getMessage());
        }
        return ArticleUnits;
	}
	public void AddMeshInfo(Node mesh_heading,List<String> mesh, List<String> major_mesh){
		NodeList meshs = mesh_heading.getChildNodes();
		String prefix = null;
		boolean qualifier = false, is_major = false;
		for(int i=0; i<meshs.getLength(); i++){
			if(meshs.item(i).getNodeName().equals("DescriptorName")){
				is_major = Is_Major(meshs.item(i));
				prefix = meshs.item(i).getTextContent();
			}
			else if(meshs.item(i).getNodeName().equals("QualifierName")){
				qualifier = true;
				String text = meshs.item(i).getTextContent();
				mesh.add(prefix+", "+text);
				if(Is_Major(meshs.item(i)))
					major_mesh.add(prefix+", "+text);
			}
		}
		
		if(prefix != null && !qualifier){
			if(is_major)
				major_mesh.add(prefix);
			mesh.add(prefix);
			
		}
	}
	public boolean Is_Major(Node node){
		String indicator = node.getAttributes().item(0).getNodeValue();
		if(indicator.equalsIgnoreCase("Y"))
			return true;
		return false;
	}
	public Name GetNameInfo(Node name){
		String forename = null, last_name = null, initials = null;
		NodeList info = name.getChildNodes();
		for(int i=0; i<info.getLength(); i++){
			if(info.item(i).getNodeName().equals("LastName"))
				last_name = info.item(i).getTextContent();
			if(info.item(i).getNodeName().equals("ForeName"))
				forename = info.item(i).getTextContent();
			if(info.item(i).getNodeName().equals("Initials"))
				initials = info.item(i).getTextContent();
		}
		Name n = new Name(last_name, forename, initials);
		return n;
	}
	public String IsOneInstance(String pmid, String title, String abstract_info){
		title = GetColdSentence(title);
		abstract_info = GetColdSentence(abstract_info);
		HashMap<String,Integer> cold_instances = new HashMap<String,Integer>();
		String localtext = null;
		List<String> instances = GetCold_Local(title);
		if(instances != null)
			for(String instance: instances){
				if(!cold_instances.containsKey(instance))
					cold_instances.put(instance, cold_instances.size());
				if(cold_instances.size()>1)
					return null;
			}
		if(instances != null && instances.size()==1)
			localtext = instances.get(0);
		instances = GetCold_Local(abstract_info);
		if(instances != null)
			for(String instance: instances){
				if(!cold_instances.containsKey(instance))
					cold_instances.put(instance, cold_instances.size());
				if(cold_instances.size()>1)
					return null;
			}
		if(cold_instances.size()==0)
      return null;
		  /* try {
				throw new Exception("There is no cold instance for "+ pmid);
			} catch (Exception e) {
				e.printStackTrace();
			}*/
		if(localtext == null)
			localtext = instances.get(0);
		return localtext;
	}
	
	public String GetColdSentence(String line){
		line = line.replaceAll("-", " ");
		line = line.toLowerCase();
		StringTokenizer st = new StringTokenizer(line,"[],.:;?!");
		StringBuffer sb = new StringBuffer();
		while(st.hasMoreTokens()){
			String token = st.nextToken();
			if(token.toLowerCase().contains("cold"))
				sb.append("\t"+token);
		}
		if(sb.toString() == null || sb.toString().length()==0)
				return null;
		return sb.toString().substring(1);
	}
	
	public List<String> GetCold_Local(String line){
		if(line == null)
			return null;
		List<String> cold_texts = new ArrayList<String>();
		String segments[] = line.split("\t");
		for(String segment: segments){
			String previous = "", follower = "";
			StringTokenizer st = new StringTokenizer(segment," [](),.:;?!/'\"");//
			while(st.hasMoreTokens()){
				String token = st.nextToken();
				if(!token.toLowerCase().contains("cold"))
					previous = token.toLowerCase();
				else{	
					if(st.hasMoreTokens()) follower = st.nextToken();
					cold_texts.add(previous+" cold "+follower);
					previous = "";
					follower = "";
				}
			}
		}
		
		return cold_texts;
	}
}
